#include <bits/stdc++.h>

using namespace std;

const int maxn=100005;
const int block_size=8192;

template <typename T> inline void read(T &r){
    char c;bool f=0;
    for(c=getchar();c>'9'||c<'0';c=getchar()) if(c=='-') f=1;
    for(r=0;c<='9'&&c>='0';c=getchar()) r=r*10+c-'0';
    if(f) r=-r;
}

int u[maxn],v[maxn],nxt[maxn],g[maxn];
int dfn[maxn],low[maxn],sta[maxn],scc[maxn];
int cnt_scc;
bool ins[maxn];

void tarjan(const int &p){
    static int clock=0;
    static int head=0;
    dfn[p]=low[p]=++clock;
    sta[head++]=p;ins[p]=1;
    for(int j=g[p];~j;j=nxt[j]){
        const int &tar=v[j];
        if(!dfn[tar]){
            tarjan(tar);
            low[p]=min(low[p],low[tar]);
        }else if(!ins[tar]) low[p]=min(low[p],dfn[tar]);
    }
    if(low[p]==dfn[p]){
        cnt_scc++;
        while(head--){
            scc[sta[head]]=cnt_scc;
            if(sta[head]==p) break;
        }
    }
}

namespace Top{ //top sort related
    int v[maxn],nxt[maxn],g[maxn],deg[maxn],q[maxn];
    int n,m;
    bitset<block_size> conn[maxn];
    struct Q{
        int x,y; //x -> y
        const bool operator < (const Q &q) const{return y<q.y;}
    };
    Q query[maxn];int lstq,qn;

    inline void addEdge(const int &x,const int &y){
        v[m]=y;nxt[m]=g[x];g[x]=m++;deg[y]++;
    }

    bool topSort(const int &l,const int &r){ //[l,r)
        int bg,ed;
        int *d = new int[maxn];
        memcpy(d,deg,sizeof deg);
        bg=ed=0;
        for(int i=1;i<=n;i++){
            conn[i].reset();
            if(!d[i]) q[ed++]=i;
        }
        for(;bg<ed;bg++){
            const int &cur=q[bg];
            if(cur>=l&&cur<r) conn[cur][cur-l]=1;
            for(int j=g[cur];~j;j=nxt[j]){
                const int &tar=v[j];
                deg[tar]--;
                conn[tar]|=conn[cur];
                if(!deg[tar]) q[ed++]=tar;
            }
        }
        for(;lstq<qn&&query[lstq].y<r;lstq++){
            if(conn[query[lstq].x][query[lstq].y-l]) return false;
        }
        return true;
    }
}

int main(){
    int n,m,t;
    bool flag;

    read(n);read(m);
    memset(g,-1,sizeof g);
    memset(Top::g,-1,sizeof Top::g);
    for(int i=1;i<=m;i++){
        int x,y;
        read(x);read(y);
        u[i]=x;v[i]=y;nxt[i]=g[x];g[x]=i;
    }
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    Top::n=cnt_scc;
    for(int i=1;i<=m;i++){
        if(scc[u[i]]!=scc[v[i]]) Top::addEdge(scc[v[i]],scc[u[i]]);
    }
    read(t);
    flag=1;
    for(int i=1;i<=t;i++){
        int x,y;
        read(x);read(y);
        x=scc[x];y=scc[y];
        if(x!=y) {Top::query[Top::qn].x=x;Top::query[Top::qn++].y=y;}
        else flag=0;
    }
    sort(Top::query,Top::query+Top::qn);

    for(int block_start=1;flag&&block_start<=Top::n;block_start+=block_size){
        int block_end=block_start+block_size;
        if(block_end>n) block_end=Top::n+1;
        flag=flag&&Top::topSort(block_start,block_end);
    }

    if(flag){
        printf("YES\n%d\n",m);
        for(int i=1;i<=m;i++) printf("%d %d\n",u[i],v[i]);
    }else printf("NO\n");

    return 0;
}
